#include "linux/module.h"
#include "linux/init.h"
#include "linux/fs.h"
#include "linux/cdev.h"
#include "linux/kdev_t.h"
#include "linux/uaccess.h"
#include "linux/delay.h"

#include "linux/atomic.h"
#include "linux/spinlock.h"
#include "linux/semaphore.h"
// static atomic64_t v = ATOMIC_INIT(1);//初始化原子变量
// static spinlock_t spinlock_test; // 定义锁
// static int flag = 1;             // 需要加锁的变量,1：没有被打开，0：被打开
struct semaphore semaphore_test;
struct chrdev
{
    dev_t dev_num;            // 设备号
    struct cdev cdev_test;    // 设备结构体
    struct class *class_test; // 设备类
} dev1;

//=================================================
static int open_test(struct inode *inode, struct file *file)
{
    // if (atomic64_read_acquire(&v)!=1)//读原子变量
    //     return -EBUSY;
    // atomic64_set_release(&v,0);//设置原子变量

    // spin_lock(&spinlock_test); // 上锁
    // if (flag != 1)             // 如果被打开立刻返回
    // {
    //     spin_unlock(&spinlock_test); 
    //     return -EBUSY;
    // }
    // flag=0;
    // spin_unlock(&spinlock_test); // 解锁

    down(&semaphore_test);
    printk(KERN_INFO "打开文件\n");
    return 0;
}
static int release_test(struct inode *inode, struct file *file)
{
    // atomic64_set_release(&v, 1);

    // spin_lock(&spinlock_test); // 上锁
    // flag=1;
    // spin_unlock(&spinlock_test); // 解锁

    up(&semaphore_test);

    printk(KERN_INFO "关闭文件\n");
    return 0;
}
static ssize_t read_test(struct file *file, char __user *buff, size_t size, loff_t *off)
{
    return 0;
}
static char kbuf[32];
static ssize_t write_test(struct file *file, const char __user *buff, size_t size, loff_t *off)
{
    int ret;
    ret = copy_from_user(kbuf, buff, size);
    if (ret != 0)
        printk(KERN_ERR "读取失败\n");

    if (strcmp(kbuf, "A") == 0)
        ssleep(4);
    else if (strcmp(kbuf, "B") == 0)
        ssleep(2);
    printk(KERN_INFO "从用户空间传递过来的数据是:%s\n", kbuf);
    return 0;
}
//=================================================

struct file_operations fops_test = {
    .owner = THIS_MODULE,
    .open = open_test,
    .release = release_test,
    .read = read_test,
    .write = write_test,
};

static int __init atomic_init(void)
{
    // spin_lock_init(&spinlock_test);
    sema_init(&semaphore_test,1);//初始化信号量并且设置为1
    alloc_chrdev_region(&dev1.dev_num, 0, 1, "atomic_test");
    printk(KERN_INFO "主设备号为:%d,次设备号为:%d\n", MAJOR(dev1.dev_num), MINOR(dev1.dev_num));
    cdev_init(&dev1.cdev_test, &fops_test); // 设备初始化cdev结构体和file_operations关联
    dev1.cdev_test.owner = THIS_MODULE;
    cdev_add(&dev1.cdev_test, dev1.dev_num, 1); // 添加设备
    dev1.class_test = class_create(THIS_MODULE, "atomic_test_class");
    device_create(dev1.class_test, NULL, dev1.dev_num, NULL, "atomic_test_drive");
    return 0;
}

static void __exit atomic_exit(void)
{
    device_destroy(dev1.class_test, dev1.dev_num);
    class_destroy(dev1.class_test);
    cdev_del(&dev1.cdev_test);
    unregister_chrdev_region(dev1.dev_num, 1);
}

module_init(atomic_init);
module_exit(atomic_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("逮就捕");
